<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>音游谱面生成器 - AI自动生成舞萌谱面</title>
    <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=Orbitron:wght@400;500;700&display=swap" rel="stylesheet">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
    <style>
        :root {
            --primary-dark: #0f172a;
            --secondary-dark: #1e293b;
            --accent-purple: #8b5cf6;
            --accent-blue: #3b82f6;
            --accent-cyan: #06b6d4;
            --text-primary: #f1f5f9;
            --text-secondary: #94a3b8;
            --success-dark: #10b981;
            --warning-dark: #f59e0b;
            --danger-dark: #ef4444;
            
            /* 谱面等级颜色 */
            /* 根据用户要求更新难度等级与颜色的对应关系 */
            --level-1: #3b82f6; /* 蓝色 - Basic */
            --level-2: #10b981; /* 绿色 - Easy */
            --level-3: #f59e0b; /* 黄色 - Normal */
            --level-4: #ef4444; /* 红色 - Hard */
            --level-5: #8b5cf6; /* 紫色 - Master */
            --level-6: #ffffff; /* 白色 - Remaster */
        }
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            background: linear-gradient(135deg, var(--primary-dark), #1a202c);
            color: var(--text-primary);
            font-family: 'Roboto', sans-serif;
            min-height: 100vh;
            padding: 20px;
        }
        
        h1, h2, h3, h4, h5, h6 {
            font-family: 'Orbitron', sans-serif;
            font-weight: 700;
        }
        
        .card {
            background: rgba(30, 41, 59, 0.8);
            border-radius: 15px;
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5);
            border: 1px solid rgba(148, 163, 184, 0.1);
            backdrop-filter: blur(10px);
            width: 100%;
            margin: 0 auto;
        }
        
        .card-header {
            background: rgba(15, 23, 42, 0.7);
            border-bottom: 1px solid rgba(148, 163, 184, 0.1);
            padding: 1.25rem 1.5rem;
        }
        
        .upload-area {
            border: 3px dashed var(--accent-purple);
            border-radius: 12px;
            padding: 40px 20px;
            text-align: center;
            background: rgba(15, 23, 42, 0.5);
            transition: all 0.3s ease;
            cursor: pointer;
            position: relative;
            overflow: hidden;
        }
        
        .upload-area:hover {
            background: rgba(30, 41, 59, 0.7);
            border-color: var(--accent-cyan);
            transform: translateY(-2px);
        }
        
        .upload-area.dragover {
            background: rgba(59, 130, 246, 0.1);
            border-color: var(--accent-blue);
        }
        
        .upload-icon {
            font-size: 3.5rem;
            color: var(--accent-purple);
            margin-bottom: 15px;
            transition: all 0.3s ease;
        }
        
        .upload-area:hover .upload-icon {
            color: var(--accent-cyan);
            transform: scale(1.1);
        }
        
        .btn-generate {
            background: linear-gradient(45deg, var(--accent-purple), var(--accent-blue));
            border: none;
            padding: 12px 30px;
            font-size: 18px;
            font-weight: 500;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }
        
        .btn-generate:hover {
            transform: translateY(-2px);
            box-shadow: 0 10px 20px rgba(139, 92, 246, 0.3);
        }
        
        .btn-generate:active {
            transform: translateY(0);
        }
        
        .btn-generate::after {
            content: '';
            position: absolute;
            top: -50%;
            left: -50%;
            width: 200%;
            height: 200%;
            background: rgba(255, 255, 255, 0.1);
            transform: rotate(30deg);
            transition: all 0.6s ease;
        }
        
        .btn-generate:hover::after {
            transform: rotate(30deg) translate(20%, 20%);
        }
        
        .btn-download {
            background: linear-gradient(45deg, var(--success-dark), #059669);
            border: none;
            padding: 12px 30px;
            font-size: 18px;
            font-weight: 500;
            transition: all 0.3s ease;
        }
        
        .btn-download:hover {
            transform: translateY(-2px);
            box-shadow: 0 10px 20px rgba(16, 185, 129, 0.3);
        }
        
        .form-select, .form-control {
            background: rgba(15, 23, 42, 0.7);
            border: 1px solid rgba(148, 163, 184, 0.3);
            color: var(--text-primary);
            border-radius: 8px;
            padding: 10px 15px;
        }
        
        .form-select:focus, .form-control:focus {
            background: rgba(30, 41, 59, 0.9);
            border-color: var(--accent-purple);
            box-shadow: 0 0 0 0.25rem rgba(139, 92, 246, 0.25);
            color: var(--text-primary);
        }
        
        .form-label {
            color: var(--text-secondary);
            font-weight: 500;
            margin-bottom: 8px;
        }
        
        .result-section {
            display: none;
        }
        
        .glowing-border {
            position: relative;
        }
        
        .glowing-border::before {
            content: '';
            position: absolute;
            top: -2px;
            left: -2px;
            right: -2px;
            bottom: -2px;
            background: linear-gradient(45deg, var(--accent-purple), var(--accent-cyan), var(--accent-blue));
            border-radius: 15px;
            z-index: -1;
            animation: glowing 3s ease infinite;
            opacity: 0.7;
        }
        
        @keyframes glowing {
            0% { opacity: 0.5; }
            50% { opacity: 1; }
            100% { opacity: 0.5; }
        }
        
        .progress {
            background: rgba(15, 23, 42, 0.7);
            background: rgba(15, 23, 42, 0.7);
            border-radius: 10px;
            height: 10px;
            overflow: hidden;
        }
        
        .progress-bar {
            background: linear-gradient(90deg, var(--accent-purple), var(--accent-cyan));
            border-radius: 10px;
            height: 100%;
            width: 0%;
            transition: width 0.3s ease;
            position: relative;
        }
        
        .alert-success {
            background: rgba(16, 185, 129, 0.15);
            border: 1px solid rgba(16, 185, 129, 0.3);
            color: #6ee7b7;
        }
        
        .alert-warning {
            background: rgba(245, 158, 11, 0.15);
            border: 1px solid rgba(245, 158, 11, 0.3);
            color: #fcd34d;
        }
        
        .alert-danger {
            background: rgba(239, 68, 68, 0.15);
            border: 1px solid rgba(239, 68, 68, 0.3);
            color: #fca5a5;
        }
        
        .difficulty-badge {
            padding: 5px 12px;
            border-radius: 20px;
            font-weight: 500;
            font-size: 0.9rem;
        }
        
        .level-badge {
            padding: 5px 12px;
            border-radius: 20px;
            font-weight: 500;
            font-size: 0.9rem;
        }
        
        /* 谱面等级颜色 */
        .level-1 { background-color: var(--level-1); }
        .level-2 { background-color: var(--level-2); }
        .level-3 { background-color: var(--level-3); }
        .level-4 { background-color: var(--level-4); }
        .level-5 { background-color: var(--level-5); }
        .level-6 { background-color: var(--level-6); color: #000; } /* 白色谱面使用黑色文字以确保可读性 */
        
        .preview-box {
            background: rgba(15, 23, 42, 0.7);
            border-radius: 10px;
            padding: 20px;
            border: 1px solid rgba(148, 163, 184, 0.2);
            max-height: 300px;
            overflow-y: auto;
            font-family: monospace;
            font-size: 0.9rem;
            white-space: pre-wrap;
        }
        
        /* 响应式设计 */
        @media (max-width: 768px) {
            body {
                padding: 10px;
            }
            
            .card {
                border-radius: 12px;
            }
            
            .upload-area {
                padding: 30px 15px;
            }
            
            .upload-icon {
                font-size: 2.5rem;
            }
            
            h1 {
                font-size: 1.8rem;
            }
            
            .btn-generate, .btn-download {
                width: 100%;
                margin-bottom: 10px;
            }
        }
        
        @media (max-width: 576px) {
            .card-body {
                padding: 1.25rem;
            }
            
            .upload-area {
                padding: 20px 10px;
            }
            
            h1 {
                font-size: 1.5rem;
            }
            
            .preview-box {
                font-size: 0.8rem;
                padding: 15px;
            }
        }
        
        /* 滚动条样式 */
        ::-webkit-scrollbar {
            width: 8px;
        }
        
        ::-webkit-scrollbar-track {
            background: rgba(15, 23, 42, 0.5);
            border-radius: 4px;
        }
        
        ::-webkit-scrollbar-thumb {
            background: var(--accent-purple);
            border-radius: 4px;
        }
        
        ::-webkit-scrollbar-thumb:hover {
            background: var(--accent-cyan);
        }
        
        /* 加载动画 */
        .spinner {
            width: 40px;
            height: 40px;
            border: 4px solid rgba(139, 92, 246, 0.3);
            border-top: 4px solid var(--accent-purple);
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin: 0 auto;
        }
        
        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }
        
        .pulse {
            animation: pulse 2s infinite;
        }
        
        @keyframes pulse {
            0% { opacity: 0.7; }
            50% { opacity: 1; }
            100% { opacity: 0.7; }
        }
        
        /* 使用Bootstrap的内置类替代自定义的flexbox样式 */
        .container-fluid {
            padding-left: 15px;
            padding-right: 15px;
        }
        
        .container-fluid.h-100 .row.h-100 {
            min-height: 100vh;
        }
        
        /* 在大屏幕上确保内容占据合适的宽度 */
        @media (min-width: 1200px) {
            .container-fluid .row {
                max-width: 1600px;
            }
        }
        
        @media (min-width: 1400px) {
            .container-fluid .row {
                max-width: 1800px;
            }
        }
        
        /* 移除多余的样式，使用Bootstrap的内置类 */
        .card {
            width: 100%;
            margin: 0 auto;
        }
        
        /* 确保在小屏幕上也能正确显示 */
        @media (max-width: 576px) {
            .container-fluid {
                padding-left: 10px;
                padding-right: 10px;
            }
        }
        
        /* Q弹按钮效果 */
        .btn-generate, .btn-download, #removeFile, #retryBtn {
            transition: transform 0.2s ease-in-out, box-shadow 0.3s ease-in-out;
        }
        
        .btn-generate:hover, .btn-download:hover, #removeFile:hover, #retryBtn:hover {
            transform: scale(1.05);
            box-shadow: 0 6px 15px rgba(0, 0, 0, 0.2);
        }
        
        .btn-generate:active, .btn-download:active, #removeFile:active, #retryBtn:active {
            transform: scale(0.98);
        }
        
        @keyframes pulse-feedback {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.05); }
        }
        
        .pulse-feedback {
            animation: pulse-feedback 0.5s ease-in-out;
        }
        
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
            20%, 40%, 60%, 80% { transform: translateX(10px); }
        }
        
        .shake {
            animation: shake 0.5s cubic-bezier(.36,.07,.19,.97) both;
        }
    </style>
</head>
<body>
    <div class="container-fluid h-100">
        <div class="row justify-content-center align-items-center h-100">
            <div class="col-xxl-8 col-xl-9 col-lg-10 col-md-11 col-sm-12">
                <div class="card mx-auto">
                    <div class="card-header text-center">
                        <h1 class="mb-0">
                            <i class="bi bi-music-note-beamed"></i> 音游谱面生成器
                        </h1>
                        <p class="text-muted mb-0 mt-2">AI驱动的舞萌谱面自动生成系统</p>
                    </div>
                    
                    <div class="card-body">
                        <form id="generateForm">
                            <div class="mb-4">
                                <label class="form-label">选择音频文件</label>
                                <div class="upload-area" id="uploadArea">
                                    <div id="dropText">
                                        <div class="upload-icon">
                                            <i class="bi bi-cloud-arrow-up"></i>
                                        </div>
                                        <h4>上传音频文件</h4>
                                        <p class="text-muted mb-1">点击选择文件或拖拽文件到此处</p>
                                        <p class="text-muted small">支持 MP3, WAV, OGG 等常见音频格式</p>
                                        <p class="text-muted small">文件大小限制: 100MB</p>
                                    </div>
                                    <input type="file" class="form-control d-none" id="audioFile" name="audio_file" accept="audio/*" required>
                                    <div id="fileInfo" class="mt-3 d-none">
                                        <span class="badge bg-primary" id="fileName"></span>
                                        <button type="button" class="btn btn-sm btn-outline-danger ms-2" id="removeFile">
                                            <i class="bi bi-x-circle"></i> 移除
                                        </button>
                                    </div>
                                </div>
                            </div>
                            
                            <div class="row">
                                <div class="col-md-6 mb-3">
                                    <label for="level" class="form-label">谱面等级 (1-6)</label>
                                    <select class="form-select" id="level" name="level">
                                        <option value="1" data-color="blue">1 - Basic (蓝谱)</option>
                                        <option value="2" data-color="green">2 - Easy (绿谱)</option>
                                        <option value="3" data-color="yellow">3 - Normal (黄谱)</option>
                                        <option value="4" selected data-color="red">4 - Hard (红谱)</option>
                                        <option value="5" data-color="purple">5 - Master (紫谱)</option>
                                        <option value="6" data-color="white">6 - Remaster (白谱)</option>
                                    </select>
                                </div>
                                
                                <div class="col-md-6 mb-3">
                                    <label for="difficulty" class="form-label">难度 (1-15)</label>
                                    <select class="form-select" id="difficulty" name="difficulty">
                                        <option value="1">1</option>
                                        <option value="2">2</option>
                                        <option value="3">3</option>
                                        <option value="4">4</option>
                                        <option value="5">5</option>
                                        <option value="6">6</option>
                                        <option value="7">7</option>
                                        <option value="7+">7+</option>
                                        <option value="8">8</option>
                                        <option value="8+">8+</option>
                                        <option value="9">9</option>
                                        <option value="9+">9+</option>
                                        <option value="10">10</option>
                                        <option value="10+">10+</option>
                                        <option value="11">11</option>
                                        <option value="11+">11+</option>
                                        <option value="12">12</option>
                                        <option value="12+">12+</option>
                                        <option value="13" selected>13</option>
                                        <option value="13+">13+</option>
                                        <option value="14">14</option>
                                        <option value="14+">14+</option>
                                        <option value="15">15</option>
                                    </select>
                                </div>
                            </div>
                            
                            <div class="d-grid">
                                <button type="submit" class="btn btn-generate btn-lg text-white">
                                    <i class="bi bi-stars"></i> 生成谱面
                                </button>
                            </div>
                        </form>
                        
                        <div class="result-section mt-4" id="resultSection">
                            <div class="alert alert-success text-center" role="alert">
                                <h4 class="alert-heading">
                                    <i class="bi bi-check-circle-fill"></i> 谱面生成成功！
                                </h4>
                                <p id="resultMessage" class="mb-3"></p>
                                <div class="d-flex justify-content-center flex-wrap gap-3 mb-3">
                                    <div>
                                        <strong>谱面等级:</strong> 
                                        <span class="level-badge" id="resultLevel"></span>
                                    </div>
                                    <div>
                                        <strong>难度:</strong> 
                                        <span class="difficulty-badge bg-warning text-dark" id="resultDifficulty"></span>
                                    </div>
                                </div>
                                
                                <div class="preview-box mb-3" id="chartPreview"></div>
                                
                                <div class="d-grid gap-2 d-md-flex justify-content-center">
                                    <button class="btn btn-download text-white me-md-2" id="downloadBtn">
                                        <i class="bi bi-download"></i> 下载谱面文件
                                    </button>
                                    <button class="btn btn-outline-light" id="newGenerationBtn">
                                        <i class="bi bi-arrow-repeat"></i> 重新生成
                                    </button>
                                </div>
                            </div>
                        </div>
                        
                        <div class="mt-4" id="loadingSection" style="display: none;">
                            <div class="text-center p-4">
                                <div class="spinner mb-3"></div>
                                <h5 class="pulse">正在分析音频并生成谱面...</h5>
                                <p class="text-muted">这可能需要几秒钟时间，请耐心等待</p>
                                <div class="progress mt-3">
                                    <div class="progress-bar" id="progressBar" role="progressbar"></div>
                                </div>
                            </div>
                        </div>
                        
                        <div class="mt-4" id="errorSection" style="display: none;">
                            <div class="alert alert-danger text-center" role="alert">
                                <h4 class="alert-heading">
                                    <i class="bi bi-exclamation-triangle-fill"></i> 错误
                                </h4>
                                <p id="errorMessage" class="mb-0"></p>
                                <button class="btn btn-outline-light mt-3" id="retryBtn">
                                    <i class="bi bi-arrow-repeat"></i> 重试
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="text-center mt-4 text-muted">
                    <p class="mb-0">
                        <i class="bi bi-shield-lock"></i> 所有音频文件均在本地处理，不会上传到服务器
                    </p>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        // 全局变量
        let audioDataBase64 = null;
        
        // DOM元素
        const uploadArea = document.getElementById('uploadArea');
        const audioFile = document.getElementById('audioFile');
        const dropText = document.getElementById('dropText');
        const fileInfo = document.getElementById('fileInfo');
        const fileName = document.getElementById('fileName');
        const removeFileBtn = document.getElementById('removeFile');
        const levelSelect = document.getElementById('level');
        const difficultySelect = document.getElementById('difficulty');
        const resultLevel = document.getElementById('resultLevel');
        const resultDifficulty = document.getElementById('resultDifficulty');
        
        // 事件监听器
        uploadArea.addEventListener('click', () => {
            audioFile.click();
        });
        
        audioFile.addEventListener('change', function() {
            if (this.files.length > 0) {
                const file = this.files[0];
                fileName.textContent = file.name;
                fileInfo.classList.remove('d-none');
                
                // 文件上传成功后给用户一个视觉反馈
                uploadArea.classList.add('pulse-feedback');
                setTimeout(() => uploadArea.classList.remove('pulse-feedback'), 500);
                
                // 读取文件为Base64
                const reader = new FileReader();
                reader.onload = function(e) {
                    audioDataBase64 = e.target.result;
                };
                reader.readAsDataURL(file);
            } else {
                fileInfo.classList.add('d-none');
                audioDataBase64 = null;
            }
        });
        
        // 移除文件
        removeFileBtn.addEventListener('click', function() {
            audioFile.value = '';
            fileInfo.classList.add('d-none');
            audioDataBase64 = null;
        });
        
        // 拖拽上传功能
        uploadArea.addEventListener('dragover', (e) => {
            e.preventDefault();
            uploadArea.classList.add('dragover');
        });
        
        uploadArea.addEventListener('dragleave', () => {
            uploadArea.classList.remove('dragover');
        });
        
        uploadArea.addEventListener('drop', (e) => {
            e.preventDefault();
            uploadArea.classList.remove('dragover');
            
            if (e.dataTransfer.files.length) {
                const file = e.dataTransfer.files[0];
                if (file.type.startsWith('audio/')) {
                    audioFile.files = e.dataTransfer.files;
                    fileName.textContent = file.name;
                    fileInfo.classList.remove('d-none');
                    
                    // 文件上传成功后给用户一个视觉反馈
                    uploadArea.classList.add('pulse-feedback');
                    setTimeout(() => uploadArea.classList.remove('pulse-feedback'), 500);
                    
                    // 读取文件为Base64
                    const reader = new FileReader();
                    reader.onload = function(e) {
                        audioDataBase64 = e.target.result;
                    };
                    reader.readAsDataURL(file);
                } else {
                    alert('请选择音频文件');
                }
            }
        });
        
        // 谱面等级选择变化时更新显示
        levelSelect.addEventListener('change', function() {
            const selectedOption = this.options[this.selectedIndex];
            const colorClass = `level-${this.value}`;
            
            // 更新结果区域的等级显示
            if (resultLevel) {
                resultLevel.className = 'level-badge ' + colorClass;
            }
        });
        
        // 表单提交处理
        document.getElementById('generateForm').addEventListener('submit', function(e) {
            e.preventDefault();
            
            if (!audioDataBase64) {
                showError('请选择一个音频文件');
                return;
            }
            
            // 显示加载状态
            document.getElementById('loadingSection').style.display = 'block';
            document.getElementById('resultSection').style.display = 'none';
            document.getElementById('errorSection').style.display = 'none';
            
            // 初始化进度条动画
            const progressBar = document.getElementById('progressBar');
            let progress = 0;
            let animationFrame;
            
            // 进度条动画函数
            function updateProgress() {
                if (progress < 95) {
                    // 前95%使用较快的进度
                    progress += Math.random() * 3 + 1;
                    if (progress > 95) progress = 95;
                } else {
                    // 超过95%后使用非常缓慢的进度
                    progress += Math.random() * 0.1;
                    if (progress > 99.9) progress = 99.9; // 防止到达100%
                }
                
                progressBar.style.width = progress + '%';
                
                // 如果仍在处理中，继续动画
                if (progress < 100) {
                    animationFrame = requestAnimationFrame(updateProgress);
                }
            }
            
            // 启动进度条动画
            updateProgress();
            
            // 获取表单数据
            const level = levelSelect.value;
            const difficulty = difficultySelect.value;
            
            // 发送请求
            fetch('/generate', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({
                    audio_data: audioDataBase64,
                    level: level,
                    difficulty: difficulty
                })
            })
            .then(response => response.json())
            .then(data => {
                // 取消进度条动画
                if (animationFrame) {
                    cancelAnimationFrame(animationFrame);
                }
                
                // 完成进度条
                progressBar.style.width = '100%';
                
                // 短暂延迟后隐藏加载界面
                setTimeout(() => {
                    document.getElementById('loadingSection').style.display = 'none';
                    
                    if (data.success) {
                        // 显示成功结果
                        document.getElementById('resultMessage').textContent = data.message;
                        
                        // 更新等级和难度显示
                        const levelText = levelSelect.options[levelSelect.selectedIndex].text;
                        resultLevel.textContent = levelText;
                        resultLevel.className = 'level-badge level-' + level;
                        
                        resultDifficulty.textContent = difficulty;
                        
                        document.getElementById('chartPreview').textContent = data.chart_content;
                        document.getElementById('resultSection').style.display = 'block';
                        
                        // 谱面生成成功后的庆祝动画
                        document.getElementById('resultSection').classList.add('shake');
                        setTimeout(() => document.getElementById('resultSection').classList.remove('shake'), 1000);
                        
                        // 设置下载链接
                        document.getElementById('downloadBtn').onclick = function() {
                            downloadChart(data.chart_file);
                        };
                    } else {
                        // 显示错误信息
                        showError(data.error);
                    }
                }, 300);
            })
            .catch(error => {
                // 取消进度条动画
                if (animationFrame) {
                    cancelAnimationFrame(animationFrame);
                }
                
                document.getElementById('loadingSection').style.display = 'none';
                console.error('Error:', error);
                showError('发生网络错误，请重试');
            });
        });
        
        // 下载谱面
        function downloadChart(filename) {
            const link = document.createElement('a');
            link.href = '/download/' + filename;
            link.download = 'maidata.txt';
            link.click();
        }
        
        // 显示错误信息
        function showError(message) {
            document.getElementById('errorMessage').textContent = message;
            document.getElementById('errorSection').style.display = 'block';
        }
        
        // 重新生成
        document.getElementById('newGenerationBtn').addEventListener('click', function() {
            document.getElementById('resultSection').style.display = 'none';
            document.getElementById('generateForm').scrollIntoView({ behavior: 'smooth' });
        });
        
        // 重试按钮
        document.getElementById('retryBtn').addEventListener('click', function() {
            document.getElementById('errorSection').style.display = 'none';
        });
        
        // 页面加载完成后的初始化
        document.addEventListener('DOMContentLoaded', function() {
            // 添加一些动画效果
            const card = document.querySelector('.card');
            card.style.opacity = '0';
            card.style.transform = 'translateY(20px)';
            
            setTimeout(() => {
                card.style.transition = 'all 0.5s ease';
                card.style.opacity = '1';
                card.style.transform = 'translateY(0)';
            }, 100);
        });
    </script>
</body>
</html>              card.style.transition = 'all 0.5s ease';
                card.style.opacity = '1';
                card.style.transform = 'translateY(0)';
            }, 100);
        });
    </script>
</body>
</html>